home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 February: Tool Chest / Dev.CD Feb 94.toast / New System Software Extensions / PlainTalk™ Speech Technologies / Text To Speech / Programming Stuff / Examples / WannaSpeech / Menu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-15  |  12.2 KB  |  443 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        Menu.c
  5. ** Written by:    Eric Soldan
  6. **
  7. ** Copyright © 1990-1993 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11. /* You may incorporate this sample code into your applications without
  12. ** restriction, though the sample code has been provided "AS IS" and the
  13. ** responsibility for its operation is 100% yours.  However, what you are
  14. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  15. ** after having made changes. If you're going to re-distribute the source,
  16. ** we require that you make it clear in the source that the code was
  17. ** descended from Apple Sample Code, but that you've made changes. */
  18.  
  19. /**************************************************************************************
  20. WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 
  21.  
  22. Changes have been made to the pristine purity of this code I have added the lines
  23. necessary to change it from AppWannaBe to WannaSpeech, the Text to Speech sample
  24. from AppleSoft Developer Technical Support
  25.  
  26.    Written by:    Guillermo A. Ortiz        AppleSoft Developer Technical Support
  27.    Date:        08/04/93
  28.  
  29. Please read WannaSpeech.readme for the gruesome details.
  30. **************************************************************************************/
  31.  
  32. /*****************************************************************************/
  33.  
  34.  
  35.  
  36. #include "App.h"            /* Get the application includes/typedefs, etc.    */
  37. #include "App.defs.h"        /* Get various application definitions.            */
  38. #include "App.protos.h"        /* Get the prototypes for application.            */
  39. #include "WannaSpeech.h"    /* Get speech stuff trying to minimize files changed */
  40.  
  41. #ifndef __DESK__
  42. #include <Desk.h>
  43. #endif
  44.  
  45. #ifndef __ERRORS__
  46. #include <Errors.h>
  47. #endif
  48.  
  49. #ifndef __MEMORY__
  50. #include <Memory.h>
  51. #endif
  52.  
  53. #ifndef __MENUS__
  54. #include <Menus.h>
  55. #endif
  56.  
  57. #ifndef __TOOLUTILS__
  58. #include <ToolUtils.h>
  59. #endif
  60.  
  61. #ifndef __UTILITIES__
  62. #include "Utilities.h"
  63. #endif
  64.  
  65.  
  66.  
  67. /*****************************************************************************/
  68.  
  69.  
  70.  
  71. extern Boolean    gQuitApplication;
  72. extern Boolean    gHasAppleEvents;
  73. extern OSType    gAppWindowType;
  74.  
  75. extern Boolean    gLowOnMem;
  76. extern short    gDialogErr;
  77.  
  78. extern Boolean gCanTalk;
  79.  
  80. /*****************************************************************************/
  81. /*****************************************************************************/
  82.  
  83.  
  84.  
  85. /* •• Called by DTS.Lib..framework. •• */
  86.  
  87. /* Adjust the menu items.  We allow the DTS.Lib framework to do most of the work
  88. ** for us.  It will walk the menubar, and for each menu in the menubar, it will
  89. ** disable all of the menu items and then call the application at either
  90. ** AdjustMenuItems() (for document and palette windows, or for the no-window case),
  91. ** or DialogAdjustMenuItems() (for modal dialogs).  The application's job is to then
  92. ** turn on menu items that should be enabled to match the current application state.
  93. ** The initial Wannabe code for AdjustMenuItems() calls DoAdjustFileMenu() for the
  94. ** file menu, and DoAdjustEditMenu() for the edit menu.  Any other menus that may
  95. ** be added to Wannabe have all menu items enabled.  This allows menus to be added
  96. ** to the running version of Wannabe and allows them to actually do something.
  97. ** If the top-most window is a dialog, then all menus are disabled except for the
  98. ** edit menu.  Various items in the edit menu are enabled, depending on if there
  99. ** is an active TextEdit control, and what is in the clipboard. */
  100.  
  101. #pragma segment Menu
  102. void    DoAdjustMenus(void)
  103. {
  104.     if (DoAdjustMBARMenus(FrontWindow(), rMenuBar))
  105.         DrawMenuBar();
  106. }
  107.  
  108.  
  109.  
  110. /*****************************************************************************/
  111.  
  112.  
  113.  
  114. /* This is called when an item is chosen from the menu bar (after calling
  115. ** MenuSelect or MenuKey).  It performs the right operation for each command.
  116. ** It is good to have both the result of MenuSelect and MenuKey go to one
  117. ** routine like this to keep everything organized. */
  118.  
  119. #pragma segment Menu
  120. Boolean    DoMenuCommand(short menuID, short menuItem)
  121. {
  122.     short        undoDepth, numUndos, saveMode, daRefNum;
  123.     Str255        daName;
  124.     FileRecHndl    frHndl;
  125.     WindowPtr    window;
  126.     TEHandle    te;
  127.     OSErr        err;
  128.     Boolean        handled;
  129.  
  130.     handled = true;
  131.  
  132.     if (window = FrontWindow())
  133.         frHndl = (FileRecHndl)GetWRefCon(window);
  134.             /* frHndl is valid only if it is one of our windows. */
  135.  
  136.     switch (menuID) {
  137.  
  138.         case mApple:
  139.             switch (menuItem) {
  140.                 case kStdAbout:        /* Bring up alert for About. */
  141.                     NewDocumentWindow(nil, 'ABOT', false);
  142.                     break;
  143.                 default:            /* All non-About items in this menu are DAs. */
  144.                     GetItem(GetMHandle(mApple), menuItem, daName);
  145.                     daRefNum = OpenDeskAcc(daName);
  146.                     break;
  147.             }
  148.             break;
  149.  
  150.         case mFile:
  151.             switch (menuItem) {
  152.                 case kStdNew:
  153.                     if (gDialogErr = NewDocumentWindow(&frHndl, gAppWindowType, true))
  154.                         NewDocumentWindow(nil, 'ERR#', false);
  155.                     break;
  156.                 case kStdOpen:
  157.                     err = OpenDocumentWindow(&frHndl, nil, fsRdWrPerm);
  158.                     if ((err) && (err != userCanceledErr)) {
  159.                         gDialogErr = err;
  160.                         NewDocumentWindow(nil, 'ERR#', false);
  161.                     }
  162.                     break;
  163.                 case kStdClose:
  164.                     if (IsAppWindow(window)) {
  165.                         if (window = FrontWindowOfType(kwIsDocument, true))
  166.                             DisposeOneWindow(window, kClose);
  167.                     }
  168.                     else
  169.                         DisposeOneWindow(window, kClose);        /* Dispose of DA window. */
  170.                     break;
  171.                 case kStdSave:
  172.                 case kStdSaveAs:
  173.                     saveMode = (menuItem == kStdSave) ? kSave : kSaveAs;
  174.                     if ((*frHndl)->fileState.refNum == kInvalRefNum)
  175.                         saveMode = kSaveAs;
  176.                     err = SaveDocument(frHndl, window, saveMode);
  177.                     if ((err) && (err != userCanceledErr)) {
  178.                         gDialogErr = err;
  179.                         NewDocumentWindow(nil, 'ERR#', false);
  180.                     }
  181.                     break;
  182.                 case kStdPageSetup:
  183.                     DoSetCursor(&qd.arrow);
  184.                     PresentStyleDialog(frHndl);
  185.                     break;
  186.                 case kStdPrint:
  187.                     DoSetCursor(&qd.arrow);
  188.                     err = noErr;
  189.                     if (!(*frHndl)->d.doc.fhInfo.printRecValid)
  190.                         err = PresentStyleDialog(frHndl);
  191.                     if (!err) {
  192.                         err = PrintDocument(frHndl, true, true);
  193.                         PrintDocument(nil, false, false);
  194.                     }
  195.                     if ((err) && (err != userCanceledErr)) {
  196.                         gDialogErr = err;
  197.                         NewDocumentWindow(nil, 'ERR#', false);
  198.                     }
  199.                     break;
  200.                 case kStdQuit:
  201.                     gQuitApplication = DisposeAllWindows();
  202.                     break;
  203.                 default:
  204.                     handled = false;
  205.                     break;
  206.             }
  207.             break;
  208.  
  209.         case mEdit:            /* Call SystemEdit for DA editing & MultiFinder. */
  210.             if (menuItem == kStdViewHier) {
  211.                 handled = false;
  212.                 break;
  213.             }
  214.             if (IsAppWindow(window)) {
  215.                 switch (menuItem) {
  216.                     case kStdUndo:
  217.                     case kStdRedo:
  218.                     case kStdCut:
  219.                     case kStdCopy:
  220.                     case kStdPaste:
  221.                     case kStdClear:
  222.                         switch ((*frHndl)->fileState.sfType) {
  223.                                 /* This is written with the assumption that document types
  224.                                 ** that demand specific code will be added.  The below “if”
  225.                                 ** illustrates how to handle the edit menu for windows that
  226.                                 ** have an active TextEdit control.  The “else” shows a typical
  227.                                 ** undo/redo scenario for applications that are using the
  228.                                 ** hierarchical document package.  The clipboard features
  229.                                 ** are of course document-dependent, so a sample hasn't been
  230.                                 ** implemented here.  For a sample, see DTS.Draw. */
  231.                             default:
  232.                                 if (te = CTEFindActive(window)) {
  233.                                     if ((*te)->viewRect.left < -8192)
  234.                                         BeginFrame(window);
  235.                                     else
  236.                                         BeginContent(window);
  237.                                     if (menuItem == kStdUndo)
  238.                                         CTEUndo();
  239.                                     else
  240.                                         CTEClipboard(menuItem - kStdCut + 2);
  241.                                     EndContent(window);
  242.                                 }
  243.                                 else {
  244.                                     if (menuItem <= kStdRedo) {
  245.                                         if (!UnmapMItem(mEdit, kStdUndo)) {
  246.                                             GetUndoInfo(frHndl, &undoDepth, &numUndos);
  247.                                             DoUndoTask((*frHndl)->d.doc.root, 1 - undoDepth, true);
  248.                                         }
  249.                                         else DoUndoTask((*frHndl)->d.doc.root, menuItem - kStdUndo, true);
  250.                                     }
  251.                                     else {
  252.                                         /* Handle rest of edit menu here. */
  253.                                     }
  254.                                 }
  255.                                 break;
  256.                         }
  257.                         break;
  258.                 }
  259.             }
  260.             else SystemEdit(menuItem - 1);
  261.             break;
  262.  
  263.         case mSpeech:
  264.             switch (menuItem) {
  265.                 case kSayIt:        /* Say the [selected] text/phonemes */
  266.                     DoSayIt(frHndl);
  267.                     break;
  268.                 case kMakePhonemes:        /* Convert the [selected] text to phonemes. */
  269.                     DoMakePhonemes(frHndl);
  270.                     break;
  271.                 case kMakeAllophones:        /* Convert the [selected] text to allophones. */
  272.                     DoMakeAllophones(frHndl); /* Galatea voices only                        */
  273.                     break;
  274.                 case kPickVoice:        /* Change the voice for document */
  275.                     SetVoice(frHndl);
  276.                     break;
  277.                 default:            /* All non-About items in this menu are DAs. */
  278.                     break;
  279.             }
  280.             break;
  281.  
  282.         default:
  283.             handled = false;
  284.             break;
  285.  
  286.     }
  287.  
  288.     return(handled);
  289. }
  290.  
  291.  
  292.  
  293. /*****************************************************************************/
  294.  
  295.  
  296.  
  297. #pragma segment Menu
  298. Boolean    DoAdjustFileMenu(WindowPtr window)
  299. {
  300.     MenuHandle    menu;
  301.     FileRecHndl    frHndl;
  302.     short        enableItem;
  303.  
  304.     menu = GetMHandle(mFile);
  305.     EnableItem(menu, UnmapMItem(mFile, kStdQuit));            /* Gotta be able to quit. */
  306.  
  307.     if (IsDAWindow(window)) {
  308.         EnableItem(menu, UnmapMItem(mFile, kStdClose));        /* Let DAs do a close from the menu. */
  309.         return(false);
  310.     }
  311.  
  312.     if (!gLowOnMem) {
  313.         EnableItem(menu, UnmapMItem(mFile, kStdNew));
  314.         EnableItem(menu, UnmapMItem(mFile, kStdOpen));
  315.     }
  316.  
  317.     if (window = FrontWindowOfType(kwIsDocument, true)) {
  318.         EnableItem(menu, UnmapMItem(mFile, kStdClose));
  319.         frHndl = (FileRecHndl)GetWRefCon(window);
  320.         if ((*frHndl)->fileState.sfType == kDocFileType) {
  321.             enableItem = GetWindowDirty(window);
  322.             if ((*frHndl)->fileState.refNum == kInvalRefNum)
  323.                 enableItem = true;
  324.             if (enableItem)
  325.                 EnableItem(menu, UnmapMItem(mFile, kStdSave));
  326.             EnableItem(menu, UnmapMItem(mFile, kStdSaveAs));
  327.         }
  328.         EnableItem(menu, UnmapMItem(mFile, kStdPageSetup));
  329.         EnableItem(menu, UnmapMItem(mFile, kStdPrint));
  330.     }
  331.  
  332.     return(false);
  333. }
  334.  
  335.  
  336.  
  337. /*****************************************************************************/
  338.  
  339.  
  340.  
  341. #pragma segment Menu
  342. Boolean    DoAdjustEditMenu(WindowPtr window)
  343. {
  344.     MenuHandle        menu;
  345.     Boolean            menuEnabled;
  346.     FileRecHndl        frHndl;
  347.  
  348.     menu = GetMHandle(mEdit);
  349.  
  350.     if (IsDAWindow(window)) {
  351.         EnableItem(menu, UnmapMItem(mEdit, kStdUndo));
  352.         EnableItem(menu, UnmapMItem(mEdit, kStdCut));
  353.         EnableItem(menu, UnmapMItem(mEdit, kStdCopy));
  354.         EnableItem(menu, UnmapMItem(mEdit, kStdPaste));
  355.         EnableItem(menu, UnmapMItem(mEdit, kStdClear));
  356.         return(false);
  357.     }
  358.  
  359.     if (IsAppWindow(window)) {
  360.         frHndl = (FileRecHndl)GetWRefCon(window);
  361.         switch ((*frHndl)->fileState.sfType) {
  362. #if VH_VERSION
  363.             case kViewHierFileType:
  364.                 CTEEditMenu(&menuEnabled, mEdit, UnmapMItem(mEdit, kStdUndo),
  365.                                                  UnmapMItem(mEdit, kStdCut));
  366.                 break;
  367. #endif
  368.             default:
  369.                 EnableItem(menu, UnmapMItem(mEdit, kStdViewHier));
  370.                 CTEEditMenu(&menuEnabled, mEdit, UnmapMItem(mEdit, kStdUndo),
  371.                                                  UnmapMItem(mEdit, kStdCut));
  372.                 break;
  373.         }
  374.     }
  375.  
  376.     return(false);
  377. }
  378. /*****************************************************************************/
  379.  
  380.  
  381.  
  382. #pragma segment Menu
  383. Boolean    DoAdjustSpeechMenu(WindowPtr window)
  384. {
  385. MenuHandle        menu;
  386. Boolean            menuEnabled;
  387. FileRecHndl        frHndl;
  388. ComponentInstance voicePicker;
  389. ControlHandle    ctl;
  390. TEHandle        te1;
  391.  
  392.     if (! gCanTalk ) /* features only make sense if TTS is available */
  393.       return false;
  394.  
  395.     if (IsDAWindow(window)) {
  396.         return(false);
  397.     }
  398.  
  399.     menu = GetMHandle(mSpeech);
  400.  
  401.     if (IsAppWindow(window)) {
  402.       frHndl = (FileRecHndl)GetWRefCon(window);
  403.  
  404.     /* Speak is enabled if there is text or phonemes/allophones to be spoken
  405.        in the active text edit field
  406.     */
  407.       te1 = CTEFindActive(nil);
  408.       if ((*te1)->hText) {
  409.         if ((*te1)->teLength)
  410.           EnableItem(menu, UnmapMItem(mSpeech, kSayIt));
  411.       }
  412.       
  413.       /* enable make phonemes when there is text to translate */
  414.       CNum2Ctl(window, kTextCtl, &ctl);
  415.       te1 = (TEHandle)GetCRefCon(ctl);
  416.       if ((*te1)->hText) {
  417.         if ((*te1)->teLength)
  418.         EnableItem(menu, UnmapMItem(mSpeech, kMakePhonemes));
  419.       }
  420.       
  421.       /* enable make allophones when there is text to translate and
  422.          current voice's synth is galatea */
  423.       CNum2Ctl(window, kTextCtl, &ctl);
  424.       te1 = (TEHandle)GetCRefCon(ctl);
  425.       if ((*te1)->hText) {
  426.         if ((*te1)->teLength) { // something to say
  427.         if ( (*frHndl)->d.doc.docSpeech.curVoice.voice.creator == 'gala' ) // and synth is gala
  428.           EnableItem(menu, UnmapMItem(mSpeech, kMakeAllophones)); // enable menu
  429.         }
  430.       }
  431.       
  432.       if (voicePicker = OpenStdTTS() ) {
  433.         EnableItem(menu, UnmapMItem(mSpeech, kPickVoice));
  434.         CloseComponent(voicePicker);
  435.       }
  436.     }
  437.  
  438.     return(false);
  439. }
  440.  
  441.  
  442.  
  443.